package memcached

import (
	"time"
	"strconv"
	"os"
	"io"
	"container/vector"
)

type Command struct {
	Name string
	Args []string
}

func serverError(msg string, c *Conn) {
	c.WriteLine("SERVER_ERROR "+msg)
}

func clientError(msg string, c *Conn) {
	c.WriteLine("CLIENT_ERROR "+msg)
}

func HandleGet(comm *Command, c *Conn, out chan<- *StoreRequest) {
	if len(comm.Args) < 1 {
		clientError("expected at least one key for "+comm.Name+" command", c)
		return
	}

	cachedVec := &vector.Vector{}
	replyc := make(chan *StoreReply)
	for _, key := range comm.Args {
		out <- &StoreRequest{
			Command: "get",
			Key:     key,
			Replyc:  replyc,
		}
		reply := <-replyc
		if reply.Ok {
			cachedVec.Push(reply.Value)
		}
	}
	for i := 0; i < cachedVec.Len(); i++ {
		cached := cachedVec.At(i).(*Cached)
		c.WriteLine("VALUE "+cached.Key+" "+strconv.Uitoa(cached.Flags)+
			" "+strconv.Itoa(len(cached.Data)))
		c.WriteBytes(cached.Data)
	}
	c.WriteLine("END")
}

func HandleSet(comm *Command, c *Conn, out chan<- *StoreRequest) {
	if len(comm.Args) != 4 {
		clientError("expected 4 arguments for set command", c)
		return
	}

	cached := &Cached{}
	cached.Key = comm.Args[0]

	var err os.Error
	cached.Flags, err = strconv.Atoui(comm.Args[1])

	if err != nil {
		clientError("invalid flags value - uint expected", c)
		return
	}

	seconds, err := strconv.Atoi64(comm.Args[2])

	if err != nil {
		clientError("invalid exptime value - uint64 expected", c)
		return
	}

	if seconds > 60*60*24*30 { // 30 days
		cached.ExpTime = time.SecondsToUTC(seconds)
	} else {
		cached.ExpTime = time.SecondsToUTC(time.UTC().Seconds() + seconds)
	}

	nbytes, err := strconv.Atoui(comm.Args[3])

	if err != nil {
		clientError("invalid bytes value - uint expected", c)
		return
	}

	data, err := c.ReadBytes(nbytes)

	if err != nil {
		if err == io.ErrUnexpectedEOF {
			clientError("unexpected end of data", c)
		} else {
			clientError("error reading data", c)
		}
	}

	cached.Data = data[:nbytes]
	replyc := make(chan *StoreReply)
	out <- &StoreRequest{
		Command: "set",
		Value:   cached,
		Replyc:  replyc,
	}
	reply := <-replyc
	if reply.Ok {
		c.WriteLine("STORED")
	} else {
		serverError("can't store data", c)
	}
}